

import React, { useReducer, useCallback } from "react";
import CacheContext from './CacheContext';
import cacheReducer from './cacheReducer';
import * as cacheTypes from './cache-types';

function KeepAliveProvider(props){
    //cacheStates存放所有的缓存信息 dispatch派发动作方法，可以通过派发动作修改缓存信息
    let [cacheStates, dispatch] = useReducer(cacheReducer, {});
    const mount = useCallback(({cacheId,element})=>{
        if(cacheStates[cacheId]){
            let cacheState = cacheStates[cacheId];
            if(cacheState.status === cacheTypes.DESTROY){
                let doms = cacheState.doms;
                doms.forEach(dom=>dom.parentNode.removeChild(dom));
                dispatch({ type: cacheTypes.CREATE, payload: { cacheId, element } });
            }
        }else{
            dispatch({type:cacheTypes.CREATE,payload:{cacheId,element}}) //创建缓存
        }
    },[cacheStates])
    let handleScroll = useCallback((cacheId,event)=>{
        if(cacheStates[cacheId]){
            let target = event.target;
            let scrolls = cacheStates[cacheId].scrolls;
            scrolls[target]=target.scrollTop;
        }
    },[cacheStates])
    return (
        <CacheContext.Provider value={{cacheStates,dispatch,mount,handleScroll}}>
            {props.children}
            {
                Object.values(cacheStates).filter(cacheState=>cacheState.status!==cacheTypes.DESTROY).map(({ cacheId, element })=>{
                    return (
                        <div
                            id={`cache_${cacheId}`}
                            key={cacheId}
                            ref={(dom) => { //如果给原生组件添加了ref,那么当此真实DOM渲染到页之后会执行回调函数,参数就这个真实dom
                                let cacheState = cacheStates[cacheId];
                                if (dom && (!cacheState.doms || cacheState.status === cacheTypes.DESTROY) ) {
                                    let doms = Array.from(dom.childNodes);
                                    dispatch({ type: cacheTypes.CREATED, payload: { cacheId, doms } });
                                }
                            }}
                        >{element}</div> //divDOM儿子们就是这个reactElement渲染出来的真实DOM
                    )
                })
            }
        </CacheContext.Provider>
    )

}

export default KeepAliveProvider;